package cn.stylefeng.guns.modular.manager.service.impl;

import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.modular.basic.service.ArchiveDictService;
import cn.stylefeng.guns.modular.basic.service.utils.TreeKit;
import cn.stylefeng.guns.modular.manager.entity.*;
import cn.stylefeng.guns.modular.manager.mapper.ArchiveInfoMapper;
import cn.stylefeng.guns.modular.manager.model.params.ArchiveInfoParam;
import cn.stylefeng.guns.modular.manager.model.params.ArchiveInfoReportParam;
import cn.stylefeng.guns.modular.manager.model.result.ArchiveInfoReport;
import cn.stylefeng.guns.modular.manager.model.result.ArchiveInfoResult;
import cn.stylefeng.guns.modular.manager.service.*;
import cn.stylefeng.guns.sys.core.constant.state.YesNo;
import cn.stylefeng.guns.sys.modular.system.entity.Dict;
import cn.stylefeng.guns.sys.modular.system.service.DeptService;
import cn.stylefeng.guns.sys.modular.system.service.DictService;
import cn.stylefeng.guns.tree.LayuiTree;
import cn.stylefeng.guns.utils.ServiceAssert;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 档案信息表 服务实现类
 * </p>
 *
 * @author blesslp
 * @since 2019-11-20
 */
@Service
public class ArchiveInfoServiceImpl extends ServiceImpl<ArchiveInfoMapper, ArchiveInfo> implements ArchiveInfoService {

    @Autowired
    private ArchiveMaterialsService archiveMaterialsService;
    @Autowired
    private ArchiveMaterialsAttachService archiveMaterialsAttachService;

    @Override
    public ArchiveInfo add(ArchiveInfoParam param) {
        ArchiveInfo entity = getEntity(param);
        //默认有效
        entity.setSfyx(YesNo.YES.getCode());
        entity.setCreatedDate(new Date());
        this.save(entity);
        return entity;
    }

    @Override
    @Transactional
    public void delete(ArchiveInfoParam param) {
        //删除档案
        final Serializable key = getKey(param);
        boolean isSuccess = this.removeById(key);
        final String TIPS = "删除成功";
        ServiceAssert.assetTrue(isSuccess, TIPS);
        //删除关联的资料
        this.archiveMaterialsService.lambdaUpdate()
                .eq(ArchiveMaterials::getDaid, key)
                .remove();
        //删除关联的附件
        this.archiveMaterialsAttachService.lambdaUpdate()
                .eq(ArchiveMaterialsAttach::getDaid, key)
                .remove();
    }

    @Override
    public ArchiveInfo update(ArchiveInfoParam param) {
        ArchiveInfo oldEntity = getOldEntity(param);
        ArchiveInfo newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
        return newEntity;
    }

    @Override
    public ArchiveInfoResult findBySpec(ArchiveInfoParam param) {
        return null;
    }

    @Override
    public List<ArchiveInfoResult> findListBySpec(ArchiveInfoParam param) {
        return null;
    }

    @Override
    public LayuiPageInfo findPageBySpec(ArchiveInfoParam param) {
        Page pageContext = getPageContext();
        if (ToolUtil.isNotEmpty(param.getDalx())) {
            final List<String> childDictWithParent = this.archiveDictService.getChildDictWithParent(param.getDalx());
            childDictWithParent.add(0, param.getDalx());
            if (ToolUtil.isNotEmpty(childDictWithParent)) {
                param.setDalxArr(childDictWithParent);
            }
        }
        IPage page = this.baseMapper.customPageList(pageContext, param);
        return LayuiPageFactory.createPageInfo(page);
    }


    @Autowired
    private ArchiveBorrowDetailService archiveBorrowDetailService;

    @Override
    public LayuiPageInfo findNoBorrowList(ArchiveInfoParam param) {
        final ArchiveInfo entity = getEntityIgnoreEmpty(param);
        //关联查出档案ids
        LambdaQueryWrapper<ArchiveBorrowDetail> details = Wrappers.lambdaQuery();
        details.select(ArchiveBorrowDetail::getDaid)
                .isNull(ArchiveBorrowDetail::getGhsj);
        //已借阅的档案ids
        List<String> daIds = this.archiveBorrowDetailService.list(details).parallelStream().map(ArchiveBorrowDetail::getDaid).collect(Collectors.toList());

        //排除已借阅的档案
        LambdaQueryWrapper<ArchiveInfo> archiveInfos = Wrappers.lambdaQuery(entity);
        if (!daIds.isEmpty()) {
            archiveInfos.notIn(ArchiveInfo::getId, daIds);
        }
//        if (ToolUtil.isNotEmpty(param.getSfyx())) {
//            archiveInfos.eq(ArchiveInfo::getSfyx, param.getSfyx());
//        }
        final IPage page = this.page(getPageContext(), archiveInfos);
        return LayuiPageFactory.createPageInfo(page);
    }

    private Serializable getKey(ArchiveInfoParam param) {
        return param.getId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private ArchiveInfo getOldEntity(ArchiveInfoParam param) {
        return this.getById(getKey(param));
    }

    private ArchiveInfo getEntity(ArchiveInfoParam param) {
        ArchiveInfo entity = new ArchiveInfo();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

    private ArchiveInfo getEntityIgnoreEmpty(ArchiveInfoParam param) {
        ArchiveInfo entity = new ArchiveInfo();
        if (ToolUtil.isEmpty(param.getSfyx())) {
            param.setSfyx(null);
        }
        if (ToolUtil.isEmpty(param.getId())) {
            param.setId(null);
        }
        if (ToolUtil.isEmpty(param.getBz())) {
            param.setBz(null);
        }
        if (ToolUtil.isEmpty(param.getDahid())) {
            param.setDahid(null);
        }
        if (ToolUtil.isEmpty(param.getDalx())) {
            param.setDalx(null);
        }
        if (ToolUtil.isEmpty(param.getGlnx())) {
            param.setGlnx(null);
        }
        if (ToolUtil.isEmpty(param.getJsnd())) {
            param.setJsnd(null);
        }
        if (ToolUtil.isEmpty(param.getLy())) {
            param.setLy(null);
        }
        if (ToolUtil.isEmpty(param.getMc())) {
            param.setMc(null);
        }
        if (ToolUtil.isEmpty(param.getMj())) {
            param.setMj(null);
        }

        if (ToolUtil.isEmpty(param.getWjid())) {
            param.setWjid(null);
        }
        if (ToolUtil.isEmpty(param.getSsrrmc())) {
            param.setSsrrmc(null);
        }
        if (ToolUtil.isEmpty(param.getSsbmid())) {
            param.setSsbmid(null);
        }
        if (ToolUtil.isEmpty(param.getNd())) {
            param.setNd(null);
        }
        if (ToolUtil.isEmpty(param.getQsnd())) {
            param.setQsnd(null);
        }
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

    @Override
    public LayuiPageInfo findBorrowList(Long id) {
        //通过借阅id查询到借阅的档案的id组
        final List<ArchiveBorrowDetail> borrowDetails = this.archiveBorrowDetailService.
                list(Wrappers.<ArchiveBorrowDetail>lambdaQuery()
                        .eq(ArchiveBorrowDetail::getDajyid, id))
                .parallelStream()
                .collect(Collectors.toList());

        if (ToolUtil.isEmpty(borrowDetails)) {
            return LayuiPageFactory.createPageInfo(getPageContext());
        }

        final Map<String, List<ArchiveBorrowDetail>> daIdsGroup = borrowDetails.stream().collect(Collectors.groupingBy(ArchiveBorrowDetail::getDaid));

        final Collection<String> daIds = daIdsGroup.keySet();

        final IPage<Map<String, Object>> maps = this.pageMaps(getPageContext(), Wrappers.<ArchiveInfo>lambdaQuery().in(ArchiveInfo::getId, daIds));

        final List<Map<String, Object>> records = maps.getRecords();

        final List<Map<String, Object>> result = records.parallelStream().map(it -> {
            final List<ArchiveBorrowDetail> borrow = daIdsGroup.get(it.get("id").toString());
            final ArchiveBorrowDetail detail = borrow.get(0);
            //把是否归还给前端，前端在删除操作的时候做验证
            it.put("sfgh", detail.getGhsj() != null ? YesNo.YES.getCode() : YesNo.NO.getCode());
            //把原档案id替换成关联表的id,方便还和删除操作
            it.put("id", detail.getId());
            return it;
        }).collect(Collectors.toList());

        maps.setRecords(result);

        return LayuiPageFactory.createPageInfo(maps);
    }


    @Autowired
    private ArchiveDestructionDetailService archiveDestructionDetailService;

    @Override
    public LayuiPageInfo listDestroy(Long id) {
        //查询出销毁关联表数据
        final List<ArchiveDestructionDetail> destructionDetails = this.archiveDestructionDetailService.list(Wrappers.<ArchiveDestructionDetail>lambdaQuery().eq(ArchiveDestructionDetail::getDaxhid, id));
        if (ToolUtil.isEmpty(destructionDetails)) {
            return LayuiPageFactory.createPageInfo(getPageContext());
        }

        //拿到档案的ids
        final List<String> ids = destructionDetails.parallelStream().map(ArchiveDestructionDetail::getDaid).collect(Collectors.toList());
        final IPage page = this.page(getPageContext(), Wrappers.<ArchiveInfo>lambdaQuery()
                .in(ArchiveInfo::getId, ids)
        );
        return LayuiPageFactory.createPageInfo(page);
    }


    @Autowired
    private DeptService deptService;
    @Autowired
    private DictService dictService;
    @Autowired
    private ArchiveDictService archiveDictService;

    /**
     * 通过nd分组
     *
     * @return
     */
    public List<LayuiTree> groupByNd() {
        final List<Map<String, Object>> allData = this.baseMapper.groupByNd();
        /* 三级结构
         *     nd - | bm - | - dalx
         *     nd   | bm   |
         *
         */
        Map<String, LayuiTree> level1 = Maps.newHashMap();
        Map<String, LayuiTree> level2 = Maps.newHashMap();
        Map<String, LayuiTree> level3 = Maps.newHashMap();

        for (Map<String, Object> allDatum : allData) {
            //年度
            LayuiTree ndNode;
            final String nd = allDatum.get("nd").toString();
            if (level1.containsKey(nd)) {
                ndNode = level1.get(nd);
            } else {
                ndNode = new LayuiTree();
                ndNode.setValue(nd);
                ndNode.setName(nd);
                level1.put(nd, ndNode);
            }

            //所属部门
            final String ssbmid = allDatum.get("ssbmid").toString();
            final String ssbmidName = allDatum.get("ssbmidName").toString();
            LayuiTree bmNode;
            final String key = ndNode.getValue() + "-" + ssbmid;
            if (level2.containsKey(key)) {
                bmNode = level2.get(key);
            } else {
                bmNode = new LayuiTree();
                bmNode.setName(ssbmidName);
                bmNode.setValue(key);
                bmNode.setParentId(ndNode.getValue());
                level2.put(key, bmNode);
            }

            //档案类型
            final String dalxId = allDatum.get("dalx").toString();
            final String dalxName = allDatum.get("dalxName").toString();
            final String key2 = key + "-" + dalxId;
            LayuiTree lxTree;
            if (level3.containsKey(key2)) {
                lxTree = level3.get(key2);
            } else {
                lxTree = new LayuiTree();
                lxTree.setName(dalxName);
                lxTree.setValue(key2);
                lxTree.setTemp(dalxId);
                lxTree.setParentId(bmNode.getValue());
                level3.put(key2, lxTree);
            }
        }

        List<LayuiTree> level3Trees = reBuildArchiveType(level3);
        return TreeKit.combine(level1.values(), level2.values(), level3Trees);
    }

    public List<LayuiTree> reBuildArchiveType(Map<String, LayuiTree> level3) {
        List<LayuiTree> level3Trees = new ArrayList<>();
        //拿到所有的类型，避免多次查询数据库
        final List<Dict> dicts = this.archiveDictService.listAllArchiveType();
        final Map<String, List<LayuiTree>> collect = level3.values().parallelStream().collect(Collectors.groupingBy(LayuiTree::getParentId));
        collect.forEach((k, v) -> {
            //key是分组关键，保持它的上级关系

            Set<LayuiTree> trees = new HashSet<>();

            //拿到改类型的code,去查询它的parent_ids,
            for (LayuiTree layuiTree : v) {

                final String dictCode = layuiTree.getTemp();
                //查询到改类型的所有父级id，
                final Triple<Long,Long, String> parentDictWithMe = this.archiveDictService.getParentDictWithMe(dictCode);
                final Long meId = parentDictWithMe.getLeft();
                final Long parentId = parentDictWithMe.getMiddle();
                final String parentsId = parentDictWithMe.getRight();
                //查询到所有父级的实体
                final List<LayuiTree> myTop = dicts.parallelStream().filter(it -> parentsId.contains(it.getDictId().toString()))
                        .map(it -> {
                            LayuiTree tree = new LayuiTree();
                            tree.setName(it.getName());
                            tree.setValue(k + "-" + it.getCode().toString());
                            tree.setParentId(it.getParentId().toString());
                            tree.setTemp(it.getDictId().toString());
                            return tree;
                        })
                        .collect(Collectors.toList());

                //把自己也放进去
                LayuiTree me = new LayuiTree();
                me.setName(layuiTree.getName());
                me.setValue(layuiTree.getValue());
                me.setParentId(parentId.toString());
                me.setTemp(meId.toString());
                myTop.add(me);
                //同一级的所有类型都一起组装
                trees.addAll(myTop);
            }

            //收集完毕， 开始组装成树
            final List<LayuiTree> layuiTrees = this.archiveDictService.buildDictTree("0", new ArrayList<>(trees));
//            拿到第一级,改装成现在的拼接形式，
            for (LayuiTree layuiTree : layuiTrees) {
                //改动原本的父级id,指向拼接的id,
                layuiTree.setParentId(k);
                level3Trees.add(layuiTree);
            }
        });
        return level3Trees;
    }

    /**
     * 通过部门分组
     *
     * @return
     */
    public List<LayuiTree> groupByBm() {
        final List<Map<String, Object>> allData = this.baseMapper.groupByNd();
        /* 三级结构
         *     nd - | bm - | - dalx
         *     nd   | bm   |
         *
         */
        Map<String, LayuiTree> level1 = Maps.newHashMap();
        Map<String, LayuiTree> level2 = Maps.newHashMap();
        Map<String, LayuiTree> level3 = Maps.newHashMap();

        for (Map<String, Object> allDatum : allData) {
            //所属部门
            final String ssbmid = allDatum.get("ssbmid").toString();
            final String ssbmidName = allDatum.get("ssbmidName").toString();
            LayuiTree bmNode;
            final String key = ssbmid;
            if (level1.containsKey(key)) {
                bmNode = level1.get(key);
            } else {
                bmNode = new LayuiTree();
                bmNode.setName(ssbmidName);
                bmNode.setValue(key);
                level1.put(key, bmNode);
            }

            //年度
            LayuiTree ndNode;
            final String nd = allDatum.get("nd").toString();
            final String keyNd = key + "-" + nd;
            if (level2.containsKey(keyNd)) {
                ndNode = level2.get(keyNd);
            } else {
                ndNode = new LayuiTree();
                ndNode.setValue(keyNd);
                ndNode.setName(nd);
                ndNode.setParentId(bmNode.getValue());
                level2.put(keyNd, ndNode);
            }

            //档案类型
            final String dalxId = allDatum.get("dalx").toString();
            final String dalxName = allDatum.get("dalxName").toString();
            final String key2 = keyNd + "-" + dalxId;
            LayuiTree lxTree;
            if (level3.containsKey(key2)) {
                lxTree = level3.get(key2);
            } else {
                lxTree = new LayuiTree();
                lxTree.setName(dalxName);
                lxTree.setValue(key2);
                lxTree.setTemp(dalxId);
                lxTree.setParentId(ndNode.getValue());
                level3.put(key2, lxTree);
            }
        }

        List<LayuiTree> level3Trees = reBuildArchiveType(level3);
        return TreeKit.combine(level1.values(), level2.values(), level3Trees);
    }

    /**
     * 通过档案位置分组
     *
     * @return
     */
    public List<LayuiTree> groupByDah() {
        final List<Map<String, Object>> maps = this.baseMapper.groupByDah();
        Map<String, LayuiTree> level1 = Maps.newHashMap();
        Map<String, LayuiTree> level2 = Maps.newHashMap();
        Map<String, LayuiTree> level3 = Maps.newHashMap();
        Map<String, LayuiTree> level4 = Maps.newHashMap();

        for (Map<String, Object> map : maps) {
            final String dahid = map.get("dahid").toString();
            final String dahidName = map.get("dahidName").toString();

            final String ssdagcid = map.get("ssdagcid").toString();
            final String ssdagcidName = map.get("ssdagcidName").toString();

            final String ssdagid = map.get("ssdagid").toString();
            final String ssdagidName = map.get("ssdagidName").toString();

            final String ssdasid = map.get("ssdasid").toString();
            final String ssdasidName = map.get("ssdasidName").toString();

            //档案室
            LayuiTree dasTree = new LayuiTree();
            dasTree.setName(ssdasidName);
            dasTree.setValue(ssdasid);
            level1.putIfAbsent(ssdasid, dasTree);

            //档案柜
            LayuiTree dagTree = new LayuiTree();
            dagTree.setName(ssdagidName);
            dagTree.setValue(ssdagid);
            dagTree.setParentId(ssdasid);
            level2.putIfAbsent(ssdagid, dagTree);

            //档案层
            LayuiTree dagcTree = new LayuiTree();
            dagcTree.setName(ssdagcidName);
            dagcTree.setValue(ssdagcid);
            dagcTree.setParentId(ssdagid);
            level3.putIfAbsent(ssdagcid, dagcTree);

            //档案盒
            LayuiTree dahTree = new LayuiTree();
            dahTree.setName(dahidName);
            dahTree.setValue(dahid);
            dahTree.setParentId(ssdagcid);
            level4.putIfAbsent(dahid, dahTree);
        }
        return TreeKit.combine(level1.values(), level2.values(), level3.values(), level4.values());
    }

    @Override
    public List<ArchiveInfoReport> report(ArchiveInfoReportParam param) {
        return this.baseMapper.report(param);
    }

}
